This chapter details the routines and processes in Tools Plus that consume memory. All of Tools Plus and the objects it creates exist in your application’s heap (the memory you allocate to an application in the “Get Info” dialog under MultiFinder or System 7). The only exception to this is Tools Plus’s global record that is used to keep its internal workings functioning. The Tools Plus global record is kept on your application’s stack. Fortunately, the global record is less than 2K, so it consumes relatively little stack space.
Almost all the objects created by Tools Plus routines are relocatable, and are therefore accessed internally by handles. The use of relocatable objects eliminates memory fragmentation caused by non-relocatable objects (locked handles, or dynamically allocated objects created by using a pointer). The only non-relocatable objects created by Tools Plus are window records, but this is not a problem providing your application calls InitToolsPlus early in the program. Calling InitToolsPlus early allocates the window records in memory where they won’t cause any heap fragmentation.
Each routine (Tools Plus or otherwise) consumes stack memory just to be able to execute its own code. After the routine has completed execution, its stack memory is automatically released. The user interface elements created by Tools Plus routines (such as buttons, list boxes, etc.) continue to occupy memory in your application’s heap until they are explicitly deleted, or their parent window is closed, or when your application ends. Tools Plus routines that consume memory only during their execution are not listed.
It is your responsibility to ensure that an operation can be completed with the amount of memory that is available in your application. For example, testing can determine the exact amount of memory required to open a window with 5 buttons, two list boxes, and 40 editing fields. Your application should ensure that the memory required to create such a window can be allocated safely before the WindowOpen statement is executed.
Editing Fields
``````````````
Each active editing field (potentially one on each standard window, and one additional field for the tool bar and all floating palettes) creates a temporary workspace to store the field’s edited text. The workspace expands as the user types characters in the field, up to a limit of 32K per active field. The workspace is released when an editing field is deactivated. Note that this workspace is still allocated when a standard window is deactivated.
You should be aware that the user can potentially consume 32K of memory just by continuing to type in an editing field. This can be averted by using length-limited editing fields, which limit the user to typing as many characters as the field can accommodate.
Measurements
````````````
Measurements of memory consumption are approximate for two very important reasons. Firstly, many objects contain handles to other objects, and because of this, they consume memory from handle blocks. Handle blocks are a pool of handles that are available to any process or object that requires them. When a process or object no longer requires a handle, the handle is released back into the available pool. Additional memory will not be required providing that the demand for handles never exceeds the available supply. As soon as the demand for handles exceeds the available supply, an additional block of 64 handles is automatically created, consuming 512 bytes of memory. An entire block will be created even if only one more handle is needed.
The second reason approximate values are provided instead of exact values, is because the Macintosh’s various managers are not always consistent in the way they allocate memory. The List Manager, for example, needs over 6K of memory the first time any of its routines are accessed (this is placed in the System heap under MultiFinder or System 7). Once that 6K kernel is loaded, memory consumption is nominal. Also, the memory consumed by various processes will likely vary between versions of the System.
Routines that consume heap space (by category)
``````````````````````````````````````````````
The following routines create objects in memory, thereby consuming heap space:
Program Initialization: InitToolsPlus
Event Polling: PollSystem
Windows: WindowOpen
WindowOpenRect
WindowTitle
ToolBarOpen
Buttons: NewButton
NewButtonRect
ButtonTitle
Picture Buttons: NewPictButton
Scroll Bars: NewScrollBar
NewScrollBarRect
Editing Field: NewField
NewFieldRect
ActivateField (if a field is not already
active)
ClickInField (if a field is not already
active)
List Boxes: NewListBox
NewListBoxRect
SetListBoxText
InsertListBoxLine
Menus: AppleMenu
Menu
InsertMenuItem
RenameItem
Pop-Up Menus: NewPopUp
NewPopUpRect
PopUpMenu
InsertPopUpItem
RenamePopUp
Cursors: CursorShape
ResetCursor
NewCursorTable
CursorZone
CursorZoneRect
CursorZoneRgn
User Notification: SetNotification
Color Drawing/
Multiple Screens: NumberOfScreens
BeginUpdateScreen
Routines that consume heap space (alphabetic)
`````````````````````````````````````````````
The following section alphabetically lists routines that create objects in memory. You will likely notice that in most cases, the amount of memory consumed is negligible.
ActivateField When an editing field is activated, it uses 8 bytes of
memory, plus 1 byte for each character of edited text.
When the editing field is deactivated, either by
deactivating it, activating another field, clicking in
another field, or closing the window, this memory is
released. Note that a user can theoretically type
thirty thousand characters (32K) into a field.
AppleMenu The Apple menu uses about 4K bytes of memory.
BeginUpdateScreen BeginUpdateScreen allocates about 40 bytes. This
memory is deallocated when EndUpdateScreen is called.
ButtonTitle Each character of the button’s title uses 1 byte of
memory. Memory consumed by any previous title is
released. Deleting the button, or closing its window
releases its memory.
ClickInField When an editing field is activated by ClickInField, it
uses 8 bytes of memory, plus 1 byte for each character
of edited text. When the editing field is
deactivated, either by deactivating it, activating
another field, clicking in another field, or closing
the window, this memory is released.
CursorShape When a cursor is displayed the first time, the CURS
resource is loaded into memory using 16 bytes of
memory. If your application has an animated cursor,
the acur resource is also loaded, using 4 bytes plus 4
bytes per animation frame.
If a resource is flagged as “purgeable” it is
automatically unloaded to reclaim memory when needed.
CursorZone Each cursor zone uses about 64 bytes of memory.
Additional memory is consumed as the zone’s region
becomes more complex. Deleting a cursor zone releases
its memory.
CursorZoneRect (Same as CursorZone)
CursorZoneRgn (Same as CursorZone)
DrawIcon When an icon is displayed the first time, the required
icon resource is loaded into memory. Depending on
your icon family, this may consume as much as 2K of
memory.
If a resource is flagged as “purgeable” it is
automatically unloaded to reclaim memory when needed.
InitToolsPlus The amount of memory consumed by InitToolsPlus is
depended upon the parameters you supply this routine,
and the development environment you are using. The
following formula provides a very good guideline:
MoreHandles x 512 bytes (creating additional
handle blocks)
+ 5K in THINK Pascal (automatically allocates 10
handle blocks)
+ MaxWindows x 430 bytes (creating window records)
+ 70K for Tools Plus libraries (smart linking
reduces this amount)
InsertListBoxLine Each line in a list box uses about 4 bytes of memory,
plus 1 byte per character of text displayed in the
line. Deleting the line in the list box, deleting its
containing list box, or closing its parent window
releases the memory used by the line.
InsertMenuItem Each menu item uses about 10 bytes of memory plus the
length of the item’s text. Deleting an item releases
its memory.
InsertPopUpItem Each pop-up menu item uses about 10 bytes of memory
plus the length of the item’s text. Deleting an item
releases its memory.
Menu Each menu uses about 36 bytes of memory. Each menu
item uses 10 bytes plus the length of the item’s
title. Deleting the menu releases its memory and that
of its associated items. Deleting an item releases
its memory.
NewButton Each button uses about 106 bytes of memory, plus the
length of the button’s title. Deleting the button, or
closing its parent window releases the button’s
memory.
NewButtonRect (Same as NewButton)
NewCursorTable Each cursor table uses about 20 bytes of memory.
Deleting a cursor table releases its memory and that
of its associated zones.
NewField Each editing field uses about 46 bytes of memory,
regardless of the number of characters used by the
field’s string. Deleting the editing field, or
closing its parent window releases the field’s memory.
NewFieldRect (Same as NewField)
NewListBox Each list box uses about 300 bytes of memory. The
first list box created will consume 6K which is
required to load the List Manager (consumes System
heap under MultiFinder, or System 7). Deleting the
list box, or closing its parent window releases the
list box’s memory and the memory used by its
associated lines.
NewListBoxRect (Same as NewListBox)
NewPictButton Each picture button uses about 64 bytes of memory.
Deleting the picture button, or closing its parent
window releases the button’s memory. When the
button’s image is displayed the first time, the
required icon or picture resource is loaded into
memory. Depending on your icon family or picture
size, this may consume as much as 2K of memory.
If a resource is flagged as “purgeable” it is
automatically unloaded to reclaim memory when needed.
NewPopUp Each pop-up menu uses 112 bytes of memory, plus the
length of the pop-up menu’s title. Deleting the
pop-up menu, or closing its parent window releases the
pop-up menu’s memory and the memory used by its
associated items.
NewPopUpRect (Same as NewPopUp)
NewScrollBar Each scroll bar uses about 70 bytes of memory.
Deleting the scroll bar, or closing its parent window
releases the scroll bar’s memory.
NewScrollBarRect (Sames as NewScrollBar)
NumberOfScreens The amount of memory consumed by NumberOfScreens
depends on the number of monitors present when your
application runs, and their settings. In the worst
case, about 40 bytes are consumed per monitor.
Note that the amount of memory consumed is not
incremented each time NumberOfScreens is called.
PollSystem All of Tools Plus’s automatic processes are kept
running when your application calls PollSystem. Some
of these processes temporarily allocate memory, while
others maintain dynamic records. It’s a good idea to
make sure your application never has less that 8K of
contiguous memory at any time. PollSystem can easily
function within those margins.
PopUpMenu Each pop-up menu item uses 10 bytes plus the length of
the item’s text. Deleting the pop-up menu releases
its memory and that of its associated items. Deleting
an item releases its memory.
RenameItem When a menu item is renamed, it uses 1 byte plus the
length of the item’s text. The memory consumed by the
previous name is released. Deleting the menu releases
its memory and that of its associated items. Deleting
an item releases its memory.
RenamePopUp When a pop-up menu item is renamed, it uses 1 byte
plus the length of the item’s text. The memory
consumed by the previous name is released. Deleting
the pop-up menu releases its memory and that of its
associated items. Deleting an item releases its
memory.
ResetCursor When a cursor is displayed the first time, the CURS
resource is loaded into memory using 16 bytes of
memory. If a resource is flagged as “purgeable” it is
automatically unloaded to reclaim memory when needed.
SetListBoxText Each line in a list box uses about 4 bytes of memory,
plus 1 byte per character of text displayed in the
line. Deleting the line in the list box, deleting its
containing list box, or closing its parent window
releases the memory used by the line.
SetNotification Setting the notification uses about 6 bytes of memory
plus the length of the message’s text. Using
SetNotification releases the memory previously used by
this routine.
ToolBarOpen The tool bar uses 340 bytes if InitToolsPlus ignores
color, and 1,250 bytes if InitToolsPlus uses color.
Closing the tool bar releases the memory
WindowOpen Each open window uses 340 bytes if InitToolsPlus
ignores color, and 1,250 bytes if InitToolsPlus uses
color. Closing the window releases the memory.
WindowOpenRect (same as WindowOpen)
WindowTitle Each character of the window’s title string uses 1
byte of memory. Memory consumed by any previous title
is released. Closing the window releases title
memory.
The Style Table
```````````````
Tools Plus uses a memory-efficient method of storing font information for objects that use styles (buttons, editing fields, list boxes and pop-up menus). The Style Table keeps a record for each unique combination of font, font size, and font style. These settings are stored in an 8-byte record that is automatically referenced by all buttons, editing fields, list boxes and pop-up menus that use those settings.
An 8-byte Style Table record is created for each unique combination of font, font size, and font style, regardless of the number of objects (buttons, editing fields, list boxes and pop-up menus) that use the same setting.
Good memory habits
``````````````````
It’s a very good idea to check the amount of available contiguous memory before allocating objects or calling a routine that may need to be loaded from disk (ie: a segment that is not yet in memory). Do the same when you open a document too, because there are a number of applications out there that bomb just because a user created a document on a 8-meg Mac and tried to open it on another Mac with less memory. Users perceive this type of behavior as being indicative of an unreliable program (“it keeps bombing on me for no reason”).